"""
线程同步-condition使用以及源码分析

condition（条件变量）：
    1.用于复杂的线程间同步
    2.线程启动顺序很重要
    3.在调用with condition之后才能调用wait或者notify方法
    4.condition有两层锁，一把底层锁会在线程调用wait方法的时候释放，
        上面的锁会在每次调用wait的时候分配一把并放入到condition的等待队列中，
        等待notify方法的唤醒。

通过condition协同读诗
"""

import threading
from threading import Condition


class XiaoAi(threading.Thread):
    def __init__(self, cond):
        self.cond = cond
        super().__init__(name="小爱")

    def run(self):
        with self.cond:
            # 等待
            self.cond.wait()
            print("{} ：在".format(self.name))
            # 通知
            self.cond.notify()

            self.cond.wait()
            print("{} ：好的，你优先".format(self.name))
            self.cond.notify()

            content = list()
            content.append("春人饮春酒，春鸟弄春声。")
            content.append("君恨我生迟，我恨君生早。")
            content.append("只虑前程远，开帆待好风。")
            content.append("闺门镇不开，梦从何处入。")
            content.append("月中三十日，无夜不相思。")
            for item in content:
                self.cond.wait()
                print("{name} ：{content}".format(name=self.name, content=item))
                self.cond.notify()


class Rokid(threading.Thread):
    def __init__(self, cond):
        self.cond = cond
        super().__init__(name="若琪")

    def run(self):
        with self.cond:
            print("{} ：小爱同学".format(self.name))
            # 通知
            self.cond.notify()
            # 等待
            self.cond.wait()

            print("{} ：我们一起来品读唐·唐无名氏的《无题》".format(self.name))
            self.cond.notify()
            self.cond.wait()

            content = list()
            content.append("春水春池满，春时春草生。")
            content.append("君生我未生，我生君已老。")
            content.append("人归万里外，意在一杯中。")
            content.append("自入长信宫，每对孤灯泣。")
            content.append("一别行千里，来时未有期。")

            for item in content:
                print("{name} ：{content}".format(name=self.name, content=item))
                self.cond.notify()
                self.cond.wait()


def use_thread():
    cond = Condition()
    xiao_ai = XiaoAi(cond)
    rokid = Rokid(cond)

    # 需要注意启动顺序
    xiao_ai.start()
    rokid.start()

    xiao_ai.join()
    rokid.join()


if __name__ == '__main__':
    use_thread()
